/*
 * DebugMonitor.java
 * 
 * Team Dovahkiin:
 * Major Bruno, Matthew Selfors
 * 
 * This class is a simulation of the Debug Monitor in the SC-2.
 */

package phaseII;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Observable;
import java.util.Scanner;

/**
 * This class is a simulation of the Debug Monitor in the SC-2.
 * 
 * @author Major Bruno
 * @author Matthew Selfors
 * @version 1.0
 */
public class DebugMonitor extends Observable {

	/**
	 * String for the directory of the program.
	 */
	private static final String PATH = "program1.hex";
	
	/**
	 * CPU object.
	 */
	protected CPU cpu;

	/**
	 * Constructor that initializes the fields and calls super().
	 */
	public DebugMonitor(final CPU the_cpu) {
		super();
		cpu = the_cpu;
	}
	
	/**
	 * Loads a program from a text file.
	 * 
	 * @throws FileNotFoundException when there
	 * 		   is no file at the specified path.
	 * @throws IOException if an I/O error occurs.
	 */
	public void loadProgram() throws FileNotFoundException, IOException {
		String temp_string;
		try {
			Scanner sc = new Scanner(new File(PATH));
			
			temp_string = sc.next();
			for (int i = 0, j = 0; i < temp_string.length(); i = i + 4) {
				if (i == 0) {
					cpu.pc.setRegValue(cpu.binarizeTheHex(temp_string.substring(i, i + 4)));
					j = cpu.decifyTheBinary(cpu.pc.getRegValue());
				} else {
					cpu.mem.setWord(j, cpu.binarizeTheHex(temp_string.substring(i, i + 4)));
					j = j + 2;
				}
			}
		} catch (Exception e) {
			System.out.println("Error: " + e.getMessage());
		}
		cpu.setHalt(false);
		
		setChanged();
		notifyObservers();
	}
	
	/**
	 * Sets the value in PC to 0x3000 and runs the currently loaded program.
	 */
	public void runProgram() {
		while (!cpu.getHalt()) {
			stepProgram();
		}
	}
	
	/**
	 * Sets the value in PC to 0x3000 and steps
	 * through the currently loaded program.
	 */
	public void stepProgram() {
		cpu.step();
		setChanged();
		notifyObservers();
	}
	
	/**
	 * Returns the register toString
	 * 
	 * @return the register toString
	 */
	public String showRegisters() {
		return cpu.registerFileToString();
	}
	
	/**
	 * Returns the memory toString
	 * 
	 * @return the memory toString
	 */
	public String showMemeory() {
		return cpu.memoryToString(cpu.decifyTheBinary(cpu.pc.getRegValue()));
	}
}
